package cn.virens.server.aio.channel.handler;

import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousCloseException;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.CompletionHandler;

import cn.virens.server.aio.channel.AioChannelSimple;

public class AioChannelReadHandler implements CompletionHandler<Integer, ByteBuffer> {
	private static final int RESET_POSITION = 0;
	private final AioChannelSimple channel;

	public AioChannelReadHandler(AioChannelSimple channel) {
		this.channel = channel;
	}

	@Override
	public void completed(Integer result, ByteBuffer buffer) {
		if (buffer != null && channel != null && channel.isOpen() && !channel.isRemove()) {
			if (result != null && result > 0 && buffer.position() >= 0) {
				buffer.limit(buffer.position());
				buffer.position(RESET_POSITION);

				// 调用数据读取监听接口
				if (channel.getAioDataReadListener() != null) {
					channel.getAioDataReadListener().onRead(channel, buffer);
				}

				// 获取对应的连接通道的读操作线程，并放进去执行解码与解析
				channel.getChannelReadRunnable().offer(buffer);
				channel.getChannelReadRunnable().execute();

				// 重置读数据用的缓存buffer
				buffer.limit(buffer.capacity());
				buffer.position(RESET_POSITION);

				// 重新开始读数据
				channel.getChannel().read(buffer, buffer, this);
				channel.setLastReadTick(System.currentTimeMillis());
			} else if (result != null && result > 0) {
				channel.getChannel().read(buffer, buffer, this);
				channel.setLastReadTick(System.currentTimeMillis());
			} else if (result == null || result <= 0) {
				channel.getAcceptHandler().unbindUid(channel);
			}
		} else {
			channel.getAcceptHandler().unbindUid(channel);
		}
	}

	@Override
	public void failed(Throwable exc, ByteBuffer buffer) {
		if (exc instanceof AsynchronousCloseException) {
			channel.getAcceptHandler().unbindUid(channel);
		} else if (exc instanceof ClosedChannelException) {
			channel.getAcceptHandler().unbindUid(channel);
		} else if (channel.getAioDataErrorListener() != null) {
			channel.getAioDataErrorListener().onError(channel, buffer, exc);
		}
	}

}
